package com.baselibrary.net;

import android.content.Context;

import androidx.collection.ArrayMap;

import com.baselibrary.BuildConfig;
import com.baselibrary.net.interceptor.CacheInterceptor;
import com.baselibrary.net.result.HttpResult;
import com.baselibrary.net.result.ResultJsonDeser;
import com.baselibrary.utils.AppUtils;
import com.baselibrary.utils.FakeX509TrustManager;
import com.baselibrary.utils.FileUtils;
import com.baselibrary.utils.SpUtils;
import com.google.gson.GsonBuilder;

import java.io.File;
import java.io.IOException;
import java.net.Proxy;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import okhttp3.Cache;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import okio.Buffer;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;

/**
 * 单利模式，创建 OKHTTP
 *
 * @author zhanglijie
 * @date 2017/6/17
 */
public class HttpHelper {

    private Retrofit mRetrofit;
    private OkHttpClient mOkHttpClient;
    private Map<String, Object> mServiceMap;


    private HttpHelper() {
    }

    public static HttpHelper getInstance() {
        return SingletonHolder.INSTANCE;
    }

    private static String bodyToString(final RequestBody request) {
        try {
            final Buffer buffer = new Buffer();
            if (request != null) {
                request.writeTo(buffer);
            } else {
                return "";
            }
            return buffer.readUtf8();
        } catch (final IOException e) {
            return "did not work";
        }
    }

    public void init(Context context, Interceptor... interceptors) {
        mServiceMap = new ArrayMap<>();
        File file = new File(FileUtils.getCacheDirPath(context), "HttpCache");
        int size = 1024 * 1024 * 50;
        Cache cache = new Cache(file, size);
        try {
            // 为请求通TLS协议，生成SSLContext对象
            SSLContext sslctxt = SSLContext.getInstance("TLS");
            // 初始化SSLContext
            sslctxt.init(null, new TrustManager[]{new FakeX509TrustManager()}, new SecureRandom());
            final X509TrustManager trustManager = new X509TrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] chain, String authType) {

                }

                @Override
                public void checkServerTrusted(X509Certificate[] chain, String authType) {

                }

                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }
            };
            OkHttpClient.Builder builder = new OkHttpClient.Builder()
                    .cache(cache)
                    .sslSocketFactory(sslctxt.getSocketFactory(),trustManager)
                    .hostnameVerifier(new HostnameVerifier() {
                        @Override
                        public boolean verify(String s, SSLSession sslSession) {
                            return true;
                        }
                    })
                    .connectTimeout(60, TimeUnit.SECONDS)
                    .readTimeout(60, TimeUnit.SECONDS)
                    .writeTimeout(60, TimeUnit.SECONDS);
            if (!BuildConfig.DEBUG) {
                builder.proxy(Proxy.NO_PROXY);
            }

            if (interceptors != null && interceptors.length > 0) {
                for (Interceptor interceptor : interceptors) {
                    builder.addInterceptor(interceptor);
                }
            }
            mOkHttpClient = builder
                    .addInterceptor(chain -> {
                        okhttp3.Request original = chain.request();
                        okhttp3. Request request = original.newBuilder()
                                .header("token", SpUtils.getInstance().getUserToken())
                                .addHeader("platform", "android")
                                .addHeader("platVersion", AppUtils.getVersionName())
                                .method(original.method(), original.body())
                                .build();

                        return chain.proceed(request);
                    })
                    .addNetworkInterceptor(new CacheInterceptor(context))
                    .build();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建ApiService
     *
     * @param clazz
     * @param baseUrl
     * @param <T>
     * @return
     */
    private <T> T createService(Class<T> clazz, String baseUrl) {
        mRetrofit = new Retrofit.Builder()
                .client(mOkHttpClient)
                .baseUrl(baseUrl)
                .addConverterFactory(
                        GsonConverterFactory.create(
                                new GsonBuilder()
                                        .registerTypeHierarchyAdapter(HttpResult.class, new ResultJsonDeser())
                                        .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
                                        .create()))
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
        return mRetrofit.create(clazz);
    }

    public <T> T getService(Class<T> clazz, String baseUrl) {
        if (mServiceMap.containsKey(clazz.getName())) {
            return (T) mServiceMap.get(clazz.getName());
        } else {
            Object obj = createService(clazz, baseUrl);
            mServiceMap.put(clazz.getName(), obj);
            return (T) obj;
        }
    }


    public <T> T getService(Class<T> clazz, String baseUrl, String interfaceName) {
        return getService(clazz, baseUrl + interfaceName);
    }

    private static class SingletonHolder {
        private static final HttpHelper INSTANCE = new HttpHelper();
    }

}
